//
//  HomeBanner.swift
//  banner
//
//  Created by 刘飞 on 2019/6/13.
//  Copyright © 2019 jimubox. All rights reserved.
//

import UIKit
//import SDWebImage

fileprivate let MarginH: CGFloat = 25
fileprivate let MarginHScale: CGFloat = 1.6
fileprivate let MarginV: CGFloat = 15

// MARK: - Banner
class Banner: UIView {
    private var _progress: CGFloat = 0.00
    fileprivate var progress: CGFloat = 0.00 {
        didSet {
            imgBanner.frame.origin.x += MarginH * MarginHScale * (progress - _progress)
            _progress = progress
        }
    }
    fileprivate var url: String? {
        didSet {
            imgBanner.sd_setImage(with: URL(string: url ?? ""), placeholderImage: nil)
        }
    }
    
    let imgBanner = UIImageView()

    override init(frame: CGRect) {
        super.init(frame: frame)
        imgBanner.frame = CGRect(x: MarginH, y: MarginV, width: self.bounds.size.width - MarginH*2, height: self.bounds.size.height - MarginV*2)
        imgBanner.layer.cornerRadius = 8
        imgBanner.layer.masksToBounds = true
        addSubview(imgBanner)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

// MARK: - HomeBanner
class HomeBanner: UIView {
    private let scrollView = UIScrollView()
    private var banners = [Banner]()
    private let count = 5
    private var currentIndex = 0
    private var displayLink: CADisplayLink?
    private var pageControl: HomePageControl?
    
    var didSelectItem: ((Int)->())?
    var urls: [String]? {
        didSet {
            guard let urls = urls, !urls.isEmpty else { return }
            pageControl?.numberOfPages = urls.count
            currentIndex = 0
            reset()
            isUserInteractionEnabled = true
            displayLink?.isPaused = false
        }
    }
    
    private func reload() {
        guard let urls = urls, !urls.isEmpty else { return }
        let page = Int(scrollView.contentOffset.x / scrollView.bounds.size.width)
        if page > count/2 {
            currentIndex = (currentIndex + (page - 2)) % urls.count
        } else if page < count/2 {
            currentIndex = (currentIndex + urls.count - (2 - page)) % urls.count
        }
        reset()
    }
    
    // left2   left1   currentIndex   right1   right2
    private func reset() {
        guard let urls = urls, !urls.isEmpty else { return }
        let left1 = (currentIndex + urls.count - 1) % urls.count
        let left2 = (currentIndex + urls.count - 2) % urls.count
        let right1 = (currentIndex + 1) % urls.count
        let right2 = (currentIndex + 2) % urls.count
        banners[2].url = urls[currentIndex]
        banners[1].url = urls[left1]
        banners[0].url = urls[left2]
        banners[3].url = urls[right1]
        banners[4].url = urls[right2]
        scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width * CGFloat(count/2), y: 0)
        
        pageControl?.currentPage = currentIndex
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubviews()
        initDisplayLink()
    }
    
    deinit {
        displayLink?.invalidate()
        displayLink = nil
    }
    
    private func initDisplayLink() {
        displayLink = CADisplayLink(target: self, selector: #selector(loop))
        displayLink?.add(to: .main, forMode: .common)
        if #available(iOS 10.0, *) {
            displayLink?.preferredFramesPerSecond = 12
        } else {
            displayLink?.frameInterval = 6
        }
        
        displayLink?.isPaused = true
    }
    
    private func addSubviews() {
        scrollView.frame = bounds
        scrollView.delegate = self
        scrollView.showsVerticalScrollIndicator = false
        scrollView.showsHorizontalScrollIndicator = false
        scrollView.isPagingEnabled = true
        scrollView.alwaysBounceHorizontal = true
        scrollView.clipsToBounds = false
        scrollView.contentSize = CGSize(width: scrollView.bounds.size.width * CGFloat(count), height: 0)
        addSubview(scrollView)
        
        let width = scrollView.bounds.size.width
        let height = scrollView.bounds.size.height
        for (index, _) in (0..<count).enumerated() {
            let x = CGFloat(index) * width
            let banner = Banner(frame: CGRect(x: x, y: 0, width: width, height: height))
            banner.imgBanner.frame.origin.x = -MarginH * ((MarginHScale-1) + MarginHScale * CGFloat(index-1))
            scrollView.addSubview(banner)
            banners.append(banner)
        }
        scrollView.contentOffset = CGPoint(x: width * CGFloat(count/2), y: 0)
        addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(tap(ges:))))
        
        pageControl = HomePageControl(frame: CGRect(x: 0, y: scrollView.bounds.size.height - 20 - MarginV, width: scrollView.bounds.size.width, height: 20))
        pageControl?.willShowNextPage = { [weak self] in
            guard let `self` = self else { return }
            self.displayLink?.isPaused = true
            self.isUserInteractionEnabled = false
            self.scrollView.setContentOffset(CGPoint(x: self.scrollView.contentOffset.x + self.scrollView.bounds.size.width, y: 0), animated: true)
        }
        addSubview(pageControl!)
    }
    
    @objc private func tap(ges: UITapGestureRecognizer) {
        if let block = self.didSelectItem {
            block(currentIndex)
        }
    }
    
    @objc private func loop() {
        pageControl?.updateCurrentPageDisplay()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension HomeBanner: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let progress = scrollView.contentOffset.x / scrollView.bounds.size.width
        for banner in banners {
            banner.progress = progress
        }
    }
    
    func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        isUserInteractionEnabled = false
        displayLink?.isPaused = true
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        isUserInteractionEnabled = true
    }
    
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        reload()
        isUserInteractionEnabled = true
        displayLink?.isPaused = false
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        reload()
        isUserInteractionEnabled = true
        displayLink?.isPaused = false
    }
}
